package DB;

import java.util.Vector;

public class Projection extends RAQuery{
	
	private Vector<String> fields;
	
/*
 * Constructor
 */
		
	public Projection(RAQuery raq, Vector<String> fields) {
		this.raQuery = raq;
		this.fields = fields;
	}

/*
 * @see DB.RAQuery#compute()
 * 
 * Computing the new Table with the right tuples, 
 * by calculating the probability in one of the two successor classes
 * DisjointProjection and IndependedProjection - depends in 
 * the safe plan algorithm
 */

	@Override
	public Table compute() {
		
		Table t = raQuery.compute();
		Table ans = new Table("", t.getKey(), orderFields(t), t.getTotalProb());
		Vector <String> currTuple = null;
		for(int i = 0; i < t.getSize(); i++){
			currTuple = t.getTuple(i);
			if(!tableContains(ans, currTuple, t)){
				ans.addTuple(project(t, currTuple), calcProb(i, t, currTuple));
			}
		}
		return ans;	
	}


/*
 * This function helps to keep the right order of the fields 
 * and not make mistakes when comparing between tuples.
 */
	
	private Vector<String> orderFields(Table t) {
		Vector<String> ans = new Vector<String>();
		for(String s : t.getTitles())
			if(fields.contains(s))
				ans.add(s);
		return ans;
	}

/*
 * checks the tuple isn't already in the answer Table
 */

	private boolean tableContains(Table ans, Vector<String> currTuple, Table t) {
		Vector<String> tupleOrderd = new Vector<String>();
		int index = 0;
		for(int i = 0 ; i < ans.getTitles().size(); i++){
			index = t.getTitles().indexOf(ans.getTitles().elementAt(i));
			tupleOrderd.add(currTuple.elementAt(index));
		}
		for (int i = 0 ; i < ans.getSize() ; i++){
			if (tuplesEqual(ans.getTuple(i), tupleOrderd))
				return true;
		}
		return false;
	}
	
/*
 * A help function for the function above - if two tuples are equal 
 */
	
	private boolean tuplesEqual(Vector<String> tTuple, Vector<String> currTuple) {
		for (int i = 0 ; i < fields.size(); i++)
			if (!tTuple.elementAt(i).equalsIgnoreCase(currTuple.elementAt(i)))
				return false;
		return true;
	}

/*
 * 	the function takes only the wanted fields of the tuple,
 * according to the fields which are "projected"
 */
	private Vector<String> project(Table t, Vector<String> currTuple) {
		Vector<String> ans = new Vector<String>();
		Vector<String> titles = t.getTitles();
		for(String s : titles){
			if(fields.contains(s))
				ans.add(currTuple.elementAt(titles.indexOf(s)));
		}
		return ans;
	}

/*
 *This function meant to be override in each of the successor classes
 */
	protected double calcProb(int i, Table t,Vector<String> currTuple) {

		return 0;
	}
	
	public boolean compareTuples(Table t, Vector<String> first, Vector<String> secound){
		
		int index = 0;
		Vector<String> titles = t.getTitles();
		for (int i = 0; i < fields.size(); i++){
			index = titles.indexOf(fields.elementAt(i));
			if (!first.elementAt(index).equals(secound.elementAt(index)))
				return false;
		}
		return true;			
	}
	

}
